package com.github.satant.api.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.github.satant.api.CacheAPI;
import com.github.satant.config.RedisConfig;
import com.github.satant.entity.CacheBean;
import com.github.satant.service.IRedisService;

@Service
public class CacheRedis
    implements CacheAPI {

  @Autowired
  private RedisConfig redisConfig;

  @Autowired
  private IRedisService redisCacheService;

  public String get(String key) {
    if (!(isEnabled())) {
      return null;
    }
    if (StringUtils.isBlank(key)) {
      return null;
    }
    CacheBean cache = getCacheBean(key);
    if (cache != null) {
      if (cache.getExpireTime().getTime() > new Date().getTime()) {
        return this.redisCacheService.get(cache.getKey());
      }
      this.redisCacheService.del(new String[]{addSys(key)});
      this.redisCacheService.del(new String[]{cache.getKey()});
    }

    return null;
  }

  public void set(String key, Object value, int expireMin) {
    set(key, value, expireMin, "");
  }

  public Long remove(String key) {
    if (!(isEnabled())) {
      return Long.valueOf(0L);
    }
    if (StringUtils.isBlank(key)) {
      return Long.valueOf(0L);
    }
    try {
      CacheBean cache = getCacheBean(key);
      if (cache != null) {
        this.redisCacheService.del(new String[]{addSys(key)});
        this.redisCacheService.del(new String[]{cache.getKey()});
      }
    } catch (Exception e) {
      return Long.valueOf(0L);
    }
    return Long.valueOf(1L);
  }

  public Long remove(String[] keys) {
    if (!(isEnabled())) {
      return null;
    }
    try {
      for (int i = 0; i < keys.length; ++i) {
        remove(keys[i]);
      }
    } catch (Exception e) {
      return Long.valueOf(0L);
    }
    return Long.valueOf(1L);
  }

  public Long removeByPre(String pre) {
    if (!(isEnabled())) {
      return Long.valueOf(0L);
    }
    if (StringUtils.isBlank(pre)) {
      return Long.valueOf(0L);
    }
    try {
      Set<String> result = this.redisCacheService.getByPre(addSys(pre));
      List<String> list = new ArrayList<String>();
      for (String key : result) {
        CacheBean cache = getCacheBean(key);
        list.add(cache.getKey());
      }
      this.redisCacheService.del((String[]) list.toArray(new String[0]));
      this.redisCacheService.delPre(addSys(pre));
    } catch (Exception e) {
      return Long.valueOf(0L);
    }
    return Long.valueOf(1L);
  }

  private CacheBean getCacheBean(String key) {
    key = addSys(key);
    CacheBean cache = null;
    try {
      cache = (CacheBean) JSON.parseObject(this.redisCacheService.get(key), CacheBean.class);
    } catch (Exception e) {
      cache = new CacheBean();
      cache.setKey(key);
      cache.setExpireTime(this.redisCacheService.getExpireDate(key));
    }
    return cache;
  }

  public String addSys(String key) {
    String result = key;
    String sys = this.redisConfig.getSysName();
    if (key.startsWith(sys)) {
      result = key;
    } else {
      result = sys + ":" + key;
    }
    return result;
  }

  public void set(String key, Object value, int expireMin, String desc) {
    if ((StringUtils.isBlank(key)) || (value == null) || (StringUtils.isBlank(value.toString()))) {
      return;
    }
    if (!(isEnabled())) {
      return;
    }
    String realValue = "";
    if (value instanceof String) {
      realValue = value.toString();
    } else {
      realValue = JSON.toJSONString(value, false);
    }
    String realKey = "i_" + addSys(key);
    Date time = new DateTime(this.redisCacheService.getExpireDate(realKey)).plusMinutes(expireMin)
        .toDate();
    CacheBean cache = new CacheBean(realKey, desc, time);
    String result = JSON.toJSONString(cache, false);
    this.redisCacheService.set(addSys(key), result, expireMin * 60);
    this.redisCacheService.set(realKey, realValue, expireMin * 60);
  }

  public List<CacheBean> listAll() {
    Set result = this.redisCacheService.getByPre(addSys(""));
    List caches = new ArrayList();
    if (result == null) {
      return caches;
    }
    Iterator it = result.iterator();
    String key = "";
    CacheBean cache = null;
    while (it.hasNext()) {
      cache = null;
      key = (String) it.next();
      try {
        cache = (CacheBean) JSON.parseObject(this.redisCacheService.get(key), CacheBean.class);
      } catch (Exception e) {
        cache = new CacheBean();
        cache.setKey(key);
        cache.setExpireTime(this.redisCacheService.getExpireDate(key));
      }
      if (cache == null) {
        continue;
      }
      cache.setKey(key);
      caches.add(cache);
    }
    return caches;
  }

  public List<CacheBean> getCacheBeanByPre(String pre) {
    if (StringUtils.isBlank(pre)) {
      return new ArrayList();
    }
    Set result = this.redisCacheService.getByPre(pre);
    Iterator it = result.iterator();
    List caches = new ArrayList();
    String key = "";
    CacheBean cache = null;
    while (it.hasNext()) {
      key = (String) it.next();
      try {
        cache = (CacheBean) JSON.parseObject(this.redisCacheService.get(key), CacheBean.class);
      } catch (Exception e) {
        cache = new CacheBean();
        cache.setKey(key);
        cache.setExpireTime(this.redisCacheService.getExpireDate(key));
      }
      cache.setKey(key);
      caches.add(cache);
    }
    return caches;
  }

  public boolean isEnabled() {
    return Boolean.parseBoolean(this.redisConfig.getEnable());
  }
}